using System;
using System.Collections;
using System.Globalization;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Web.Management;


namespace Ajax.Logging
{
    public class WebEventLogProvider : ExceptionLogProvider
    {
        [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", Justification = "Assembly is not localized")]
        public override void Initialize(string name, NameValueCollection config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            if (string.IsNullOrEmpty(name))
            {
                name = "WebEventLogProvider";
            }

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "WebEventLogProvider");
            }

            base.Initialize(name, config);
        }

        public override void Log(ExceptionInfo exception)
        {
            WebClientExceptionEvent exceptionEvent = new WebClientExceptionEvent(this, exception);
            exceptionEvent.Raise();
        }
    }

    public class WebClientExceptionEvent : WebBaseEvent
    {
        private ExceptionInfo _exception;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
        public WebClientExceptionEvent(object source, ExceptionInfo exception):base(exception.Message, source, exception.Code)
        {
            _exception = exception;
        }

        public override void FormatCustomEventDetails(WebEventFormatter formatter)
        {
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "UserName: {0}", _exception.UserName));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "Authenticated: {0}", _exception.IsAuthenticated.ToString(CultureInfo.CurrentCulture)));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "UserAgent: {0}", _exception.UserAgent));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "IPAddress: {0}", _exception.IPAddress));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "Dns: {0}", _exception.Dns));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "Type: {0}", GetNotAvailableIfEmpty(_exception.Type)));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "Description: {0}", GetNotAvailableIfEmpty(_exception.Message)));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "StackTrace: {0}", GetNotAvailableIfEmpty(_exception.StackTrace)));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "LineNumber: {0}", _exception.LineNumber.ToString(CultureInfo.CurrentCulture)));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "Url: {0}", _exception.Url));
            formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "Referrer: {0}", GetNotAvailableIfEmpty(_exception.Referrer)));

            if (_exception.Scripts.Count > 0)
            {
                formatter.AppendLine("Scripts:");
                formatter.IndentationLevel += 1;

                foreach (string script in _exception.Scripts)
                {
                    formatter.AppendLine(script);
                }

                formatter.IndentationLevel -= 1;
            }

            if (_exception.Cookies.Count > 0)
            {
                formatter.AppendLine("Cookies:");
                formatter.IndentationLevel += 1;

                foreach (KeyValuePair<string, string> cookie in _exception.Cookies)
                {
                    formatter.AppendLine(string.Format(CultureInfo.CurrentCulture, "{0} : {1}", cookie.Key, cookie.Value));
                }

                formatter.IndentationLevel -= 1;
            }

            base.FormatCustomEventDetails(formatter);
        }

        private static string GetNotAvailableIfEmpty(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return "n/a";
            }

            return value;
        }
    }
}